package net.esj.basic.utils.id;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.Assert;

import net.esj.basic.plugins.hibernate.id.TimeSerialIdGenerator.Sequenced;
import net.esj.basic.utils.DateUtils;

public class TimeSerialIdGenerator {

	private static Map<String,Sequenced> lastIdMap = new HashMap<String,Sequenced>();
	
	private static final NumberFormat nf = new DecimalFormat("0000");
	
	public static String generate(String cate,String resource){
		Assert.notNull(cate);
		Assert.notNull(resource);
		StringBuilder sb = new StringBuilder();
		
		sb.append(cate).append(resource);
		
		String timePart = formatTime(DateUtils.now());
		Sequenced sequenced;
		synchronized(TimeSerialIdGenerator.class){
			String keyDep = sb.toString();
			sequenced = lastIdMap.get(keyDep);
			if(sequenced==null){
				sequenced = new Sequenced(timePart);
				lastIdMap.put(keyDep, sequenced);
			}
		}
		synchronized(sequenced){
			if(sequenced.getTimePartToLong()<Long.valueOf(timePart)){
				sequenced.setSerial(0);
			}
			sb.append(getAdapterAddress()).append(timePart).append(formateSerial(sequenced.increaseAndGetSerial()));
		}
		return sb.toString();
	}
	
	private static String formateSerial(long serial){
		return nf.format(serial);
	}
	
	private static final DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

	private static String formatTime(Date date){
		return df.format(date);
	}
	
	private static String getAdapterAddress() {
		 byte addr[];
		try {
			addr = InetAddress.getLocalHost().getAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
			addr = new byte[]{0,0,0,0};
		}
		 
		 StringBuffer sb = new StringBuffer();
		 
         for(byte b : addr){
        	 String s = Integer.toHexString(b & 0xFF);
 				sb.append(s.length() == 1 ? 0 + s : s);
         }
		// 把字符串所有小写字母改为大写成为正规的mac地址并返回
		return sb.toString().toUpperCase();
	}
	
	public static class Sequenced {
		private String timePart;

		private long serial = 0;
		
		public Sequenced(String timePart) {
			super();
			this.timePart = timePart;
		}

		public String getTimePart() {
			return timePart;
		}

		public long getTimePartToLong(){
			return Long.valueOf(timePart);
		}
		
		public void setTimePart(String timePart) {
			this.timePart = timePart;
		}

		public long getSerial() {
			return serial;
		}

		public void setSerial(long serial) {
			this.serial = serial;
		}
		public synchronized long increaseAndGetSerial(){
			this.serial = this.serial+1;
			return serial;
		}
	}
	
	public static void main(String[] args){
		System.out.println(df.format(new Date()));
	}
}
